#pragma once
#include <cstdlib>
#include <ctime>
#include "Board.h"
#include "float.h"
#include "Frame.h"
#include "GreedySolver.cpp"
#define epsilon 1.0e-6

using std::vector;


class MCTreeNode
{
public:
	int turn, level, winner;
	double nVisits, totValue; // 分别是访问次数和总的收益值
	int ExistChild, TotalChild;
	double AvgValue;
	static int nodeCount;
	static int	simCount;
	MCTreeNode* father;
	MCTreeNode(Board* board, int turn, Step* step, int level)
	{
		this->board = board;
		this->turn = turn;
		this->step = step;
		this->level = level;
	}


	MCTreeNode(Board* board, MCTreeNode* father,int turn, Step* step, int level)
	{
		this->board = board;
		this->turn = turn;
		this->step = step;
		this->level = level;
		this->father = father;
		TotalChild = board->get_available_steps().size();
		ExistChild = 0;
	}
	~MCTreeNode()
	{


		//如果是叶子节点(没有儿子了)
		if (children != nullptr)
		{
			for (int i = 0; i < children->size(); i++)
			{
				delete children->at(i);
				if (children->size() == 0)
					return;
			}
		}


		delete board;
		board = nullptr;
		delete step;
		step = nullptr;
		if (children != nullptr)
		{
			delete children;
		}
		children = nullptr;
	}

	//拓展
	void expand()
	{
		//如何搜索深度到了
		if (level == maxLevel)
		{
			children = nullptr;
			return;
		}

		//可用步数
		vector<Step*>* steps = new vector<Step*>();

		vector<Step> steps_ = board->get_available_steps();

		for (Step s : steps_)
		{
			steps->push_back(new Step(s));
		}


		//如果已经是全局的叶子节点
		if (steps->size() == 0)
		{
			children = nullptr;
			delete steps;
			return;
		}

		//new出子节点容器
		children = new vector<MCTreeNode*>();

		//遍历生成子节点
		for (int i = 0; i < steps->size(); i++)
		{
			Board* next_board = board->get_new_board(turn, steps->at(i)->dir, steps->at(i)->x, steps->at(i)->y);
			children->push_back(new MCTreeNode(next_board, this, (board->get_current_player_score(turn) < next_board->get_current_player_score(turn) ? turn : next_board->toggle_round(turn)), steps->at(i), level + 1));
			nodeCount++;
		}
		delete steps;

	}


	MCTreeNode* ExpandUCTNode()
	{

		return nullptr;
	}


	double getValue(double pVisits)
	{

		// TODO UCT 公式
		//return double(totValue / nVisits) +

		double mid = sqrt(log(pVisits + 1) / (nVisits + epsilon));
		return 1 - totValue / (nVisits + epsilon) + mid;
		//return (totValue / nVisits + epsilon) + sqrt(log(pVisits + 1) * 2 / (nVisits + epsilon));
		//return AvgValue + sqrt((((log10((double)totValue)) * 2) / (double)nVisits));
	}

	double getValue()
	{

		return (totValue / nVisits) + epsilon * sqrt(log(father->nVisits) * 2 / (nVisits));
	}

	//挑选
	Step* getMove()
	{
		double bestValue = -1000000000000;
		Step* bestStep = nullptr;

		//挑选子节点中分值最大的那个
		for (MCTreeNode* child : *children)
		{
			double currentValue = child->getValue();
			if (currentValue > bestValue)
			{
				bestValue = currentValue;
				bestStep = child->getStep();
			}
		}

		printf("最佳获得分数为%f \n", bestValue);
		printf("最佳步为[%d,%d,%d] \n", bestStep->dir, bestStep->x, bestStep->y);
		return bestStep;
	}


	double RefreshAvgValue()
	{
		double Value = 0;

		for (int i = 0; i < children->size(); i++)
		{
			Value += children->at(i)->AvgValue;
		}

		AvgValue = 1 - (Value / (double)children->size());

		return AvgValue;
	}




	double GetUCBValue()
	{
		return AvgValue + sqrt((((log10((double)totValue)) * 2) / (double)nVisits));
	}

	double getAverageValue() 
	{
		return totValue / nVisits;
	}

	Step* getStep()
	{
		return step;
	}

	void updateStats(double value)
	{
		this->nVisits++;
		this->totValue += value;
	}

	int getTurn()
	{
		return turn;
	}

	double getVisits()
	{
		return nVisits;
	}

	Board* getBoard()
	{
		return board;
	}

	vector<MCTreeNode*>* getChildren()
	{
		return children;
	}


	//得到这个局势的胜利者
	int getBoardWinner(Board* board, int turn)
	{
		int winner;

		if (board->isComplete())
		{
			return board->getScore(RED_) > board->getScore(BLUE_) ? RED_ : BLUE_;
		}
		else
		{
			GreedySolver* tempSolver = new GreedySolver();
			Step step = tempSolver->solve(board, turn);
			delete tempSolver;

			Board* nextBoard = board->get_new_board(turn, step.dir, step.x, step.y);
			winner = getBoardWinner(nextBoard, (nextBoard->getScore(turn) > board->getScore(turn) ? turn : board->toggle_round(turn)));
			delete nextBoard;
			return winner;
		}
	}

private:
	//最大搜索层数
	const static int maxLevel = 10;
	Board* board;
	Step* step;
	vector<MCTreeNode*>* children;

};

